package net.ib.mtalk.ui.chat;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

import net.ib.mntalk.protocol.Common;
import net.ib.mntalk.protocol.Common.FileKey;
import net.ib.mntalk.protocol.Common.Message;
import net.ib.mntalk.protocol.Common.UUIDMsg;
import net.ib.mntalk.protocol.Common.UUIDSliceRange;
import net.ib.mntalk.protocol.Common.UserMessage;
import net.ib.mntalk.protocol.File.ImageOption;
import net.ib.mntalk.protocol.Session.AcquireFileTokenRes;
import net.ib.mntalk.protocol.Session.AddMembersReq;
import net.ib.mntalk.protocol.Session.GetMembersReq;
import net.ib.mntalk.protocol.Session.GetMessagesReq;
import net.ib.mntalk.protocol.Session.SendMessageReq;
import net.ib.mtalk.R;
import net.ib.mtalk.constant.MTalkConstant;
import net.ib.mtalk.database.DatabaseContract.MessageTable.MessageProperty;
import net.ib.mtalk.database.helper.InboxDatabaseHelper;
import net.ib.mtalk.database.task.DBBackupHistoryMessagesTask;
import net.ib.mtalk.database.task.DBInsertSendMessage;
import net.ib.mtalk.database.task.DBUpdateViewUuidTask;
import net.ib.mtalk.database.task.DBcheckDeleteViewTask;
import net.ib.mtalk.global.GlobalPreferences;
import net.ib.mtalk.network.NetResultReceiver;
import net.ib.mtalk.network.task.AddMembersTask;
import net.ib.mtalk.network.task.DeliverMessagesTask;
import net.ib.mtalk.network.task.DeliverReadMarksTask;
import net.ib.mtalk.network.task.FileDownloadTask;
import net.ib.mtalk.network.task.FileUploadTask;
import net.ib.mtalk.network.task.GetMembersTask;
import net.ib.mtalk.network.task.GetMessagesTask;
import net.ib.mtalk.network.task.SendMessageTask;
import net.ib.mtalk.network.task.SubscribeTask;
import net.ib.mtalk.network.task.UnsubscribeTask;
import net.ib.mtalk.ui.UIController;
import net.ib.mtalk.util.GpbSupport;
import net.ib.mtalk.util.MTalkLogWriter;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.widget.Toast;

import com.google.protobuf.micro.ByteStringMicro;

/**
 * 
 * @author eugenel
 *
 */
public class ChatController extends UIController {
	
	private NetResultReceiver mDeliverMessageReceiver;
	private NetResultReceiver mDeliverReadMark;

	public ChatController(Context context, Handler handler, UUID clientViewUuid){
		super(context, handler);
		deliverMessages(clientViewUuid);
		deliverReadMarks(clientViewUuid);
	}
	
	private void deliverMessages(UUID clientViewUuid){
		DeliverMessagesTask deliverMessagesTask = new DeliverMessagesTask(mContext, mUiHandler);
		mDeliverMessageReceiver = new NetResultReceiver(this.mUiHandler, deliverMessagesTask);
	}
	
	private void deliverReadMarks(UUID clientViewUuid){
		DeliverReadMarksTask deliverReadMarksTask = new DeliverReadMarksTask(mContext, mUiHandler);
		mDeliverReadMark = new NetResultReceiver(this.mUiHandler, deliverReadMarksTask);
	}
	
	/**
	 * 새로운 뷰 UUID로 메시지 및 View 를 업데이트한다. 
	 * @param viewUuidMsb
	 * @param viewUuidLsb
	 */
	public void updateViewUuid(){
		try{
			MTalkLogWriter.d("ChatController.updateViewUuid()");
			DBUpdateViewUuidTask task = new DBUpdateViewUuidTask(mContext, mUiHandler);
			task.execute();
		}catch(Exception e){
			MTalkLogWriter.e(e);
		}
	}
	
	public void checkDeleteView(long viewUuidMsb, long viewUuidLsb){
		try{
			DBcheckDeleteViewTask task = new DBcheckDeleteViewTask(mContext, mUiHandler, viewUuidMsb, viewUuidLsb);
			task.execute();
		} catch(Exception e){
			MTalkLogWriter.e(e);
		}
	}
	/**
	 * 메시지를 전송하는 로직 추가
	 * @param message
	 */
	public void sendMessage(SendMessageReq message, long clientViewUuidMsb, long clientViewUuidLsb, UUID clientMsgUuid){
		try{
			MTalkLogWriter.d("ChatController.sendMessage()");
			SendMessageTask task = new SendMessageTask(mContext, mUiHandler, message, clientViewUuidMsb, clientViewUuidLsb, clientMsgUuid);
			task.execute();
		} catch(Exception e) {
			MTalkLogWriter.e(e);
		}
	}
	
	public void onSubscribe(long clientViewUuidMsb, long clientViewUuidLsb){
		try{
			SubscribeTask task = new SubscribeTask(mContext, mUiHandler, clientViewUuidMsb, clientViewUuidLsb, mDeliverMessageReceiver, mDeliverReadMark);
			task.execute();
		} catch(Exception e) {
			MTalkLogWriter.e(e);
		}
	}
	
	public void onUnsubscribe(long clientViewUuidMsb, long clientViewUuidLsb){
		try{
			UnsubscribeTask task = new UnsubscribeTask(mContext, clientViewUuidMsb, clientViewUuidLsb);
			task.execute();
		} catch(Exception e) {
			MTalkLogWriter.e(e);
		}
	}
	
	public void getMembers(long clientViewUuidMsb, long clientViewUuidLsb){
		try{
			UUIDSliceRange range = new UUIDSliceRange();
			range.setAscending(false);
			range.setMaxCount(ChatListActivity.GET_MEMBER_COUNT);
			
			GetMembersReq getMembersReq = new GetMembersReq();
			getMembersReq.setViewUuid(InboxDatabaseHelper.getViewUUID(mContext, clientViewUuidMsb, clientViewUuidLsb));
			getMembersReq.setRange(range);
			
			GetMembersTask task = new GetMembersTask(mContext, mUiHandler, clientViewUuidMsb, clientViewUuidLsb, getMembersReq);
			task.execute();
		}catch(Exception e){
			MTalkLogWriter.e(e);
		}
	}
	
	public void sendAttachment(UUID clientViewUuid, UUIDMsg viewUuid, String fileContent, String fileName, MessageProperty type, UUID clientMsgUuid){
		if(fileContent !=null && !fileContent.equals("")){
			Common.UserMessage userMessage = new Common.UserMessage();
			userMessage.setContentType(Common.CONTENT_TYPE_ATTACHMENT);
			userMessage.setSenderUuid(GlobalPreferences.getUserUUID());
			userMessage.setSenderName(GlobalPreferences.getUserName());
			
			// 전송을 하자!
			// UserMessage를 만들어보자.
			Common.Attachment attachment = new Common.Attachment();
			attachment.setFileName(fileName);
			if(type.equals(MessageProperty.CALENDAR)){
				userMessage.setContent(mContext.getString(R.string.attachment_vcalendar_name));
				attachment.setMimeType(MTalkConstant.MIME_TYPE_VCALENDAR);					
			}else if(type.equals(MessageProperty.CONTACT)){				
				userMessage.setContent(mContext.getString(R.string.attachment_vcard_name));
				attachment.setMimeType(MTalkConstant.MIME_TYPE_VCARD);
			}else if(type.equals(MessageProperty.GEOTAG)){
				userMessage.setContent(mContext.getString(R.string.attachment_geotag_name));
				attachment.setMimeType(MTalkConstant.MIME_TYPE_GEOTAG);
			}else{
				userMessage.setContent("Other");
				attachment.setFileName("Other");
				attachment.setMimeType("Other");
			}
			
			attachment.setContent(ByteStringMicro.copyFromUtf8(fileContent));
			
			userMessage.setAttachment(attachment);
			
			SendMessageReq sendMessageReq = new SendMessageReq();
			sendMessageReq.setViewUuid(viewUuid);
			sendMessageReq.setMessage(userMessage);
			
			DBInsertSendMessage dbtask = new DBInsertSendMessage(mContext, mUiHandler, clientViewUuid, sendMessageReq, type, null, clientMsgUuid);
			dbtask.execute();
			
			SendMessageTask task = new SendMessageTask(mContext, mUiHandler, sendMessageReq, clientViewUuid, clientMsgUuid);
			task.execute();
		}
	}
	
//	public void sendAttachment(UUID clientViewUuid, UUIDMsg viewUuid, String data, MessageProperty type, UUID clientMsgUuid){
//			// UserMessage를 만들어보자.
//			Common.UserMessage userMessage = new Common.UserMessage();
//			userMessage.setContentType(Common.CONTENT_TYPE_ATTACHMENT);
//			userMessage.setSenderUuid(GlobalPreferences.getUserUUID());
//			userMessage.setSenderName(GlobalPreferences.getUserName());
//			
//			Common.Attachment attachment = new Common.Attachment();
//			if(type.equals(MessageProperty.CALENDAR)){
//				userMessage.setContent(mContext.getString(R.string.attachment_vcalendar_name));
//				attachment.setFileName("CALENDAR");
//				attachment.setMimeType(MTalkConstant.MIME_TYPE_VCALENDAR);					
//			}else if(type.equals(MessageProperty.CONTACT)){					
//				userMessage.setContent(mContext.getString(R.string.attachment_vcard_name));
//				attachment.setFileName("CONTACT");
//				attachment.setMimeType(MTalkConstant.MIME_TYPE_VCARD);
//			}else if(type.equals(MessageProperty.GEOTAG)){					
//				userMessage.setContent(mContext.getString(R.string.attachment_geotag_name));
//				attachment.setFileName("GEOTAG");
//				attachment.setMimeType(MTalkConstant.MIME_TYPE_GEOTAG);
//			}else{				
//				attachment.setFileName("Other");
//				attachment.setMimeType("Other");
//			}
//			
//			attachment.setContent(ByteStringMicro.copyFromUtf8(data));
//			
//			userMessage.setAttachment(attachment);
//			
//			SendMessageReq sendMessageReq = new SendMessageReq();
//			sendMessageReq.setViewUuid(viewUuid);
//			sendMessageReq.setMessage(userMessage);
//			
//			DBInsertSendMessage dbtask = new DBInsertSendMessage(mContext, mUiHandler, clientViewUuid, sendMessageReq, type, null, clientMsgUuid);
//			dbtask.execute();
//			
//			// 전송을 하자!
//			SendMessageTask task = new SendMessageTask(mContext, mUiHandler, sendMessageReq, clientViewUuid, clientMsgUuid);
//			task.execute();
//	}
	
	public void setFileSendMessage(long clientViewUuidMsb, long clientViewUuidLsb, UUIDMsg viewUuid, Uri fileUri, int fileType, UUID clientMsgUuid){
		try{
			File file = new File(fileUri.getPath());
			file.getName();
			
			FileKey fileKey = new FileKey();
			fileKey.setFileType(fileType);
			// 더미 UUID
			fileKey.setFileUuid(GpbSupport.makeUuidMsg(UUID.randomUUID()));
			fileKey.setFileName(file.getName());
			
			UserMessage um = new UserMessage();
			um.setSenderName(GlobalPreferences.getUserName());
			um.setSenderUuid(GlobalPreferences.getUserUUID());
			um.setContentType(Common.CONTENT_TYPE_HTML);
			um.setAttachFile(fileKey);
			
			MessageProperty property;
			switch(fileType){
				case Common.FT_PROFILE_IMG:
					um.setContent("프로필");
					property = MessageProperty.IMAGE;
					break;
				case Common.FT_IMG:
					um.setContent("이미지");
					property = MessageProperty.IMAGE;
					break;
				case Common.FT_AUDIO:
					um.setContent("오디오");
					property = MessageProperty.RECORD;
					break;
				case Common.FT_VIDEO:
					um.setContent("비디오");
					property = MessageProperty.VIDEO;
					break;
				default:
					um.setContent(" ");
					property = MessageProperty.TEXT;
			}
						
			SendMessageReq sendMessageReq = new SendMessageReq();
			sendMessageReq.setViewUuid(viewUuid);
			sendMessageReq.setMessage(um);
			MTalkLogWriter.d("sendMessageReq : " + sendMessageReq.getMessage().getContent());
			DBInsertSendMessage task = new DBInsertSendMessage(mContext, mUiHandler, clientViewUuidMsb, clientViewUuidLsb, 
					sendMessageReq, property, fileUri, clientMsgUuid);
			task.execute();
		}catch(Exception e){
			MTalkLogWriter.e(e);
		}
	}
	
	public void sendFile(UUID clientViewUuid, UUIDMsg messageUuid, Uri fileUri, int fileType, UUID clientMsgUuid){
		try{
			FileUploadTask task = new FileUploadTask(mContext, mUiHandler, clientViewUuid, messageUuid, clientMsgUuid, fileUri, fileType);
			task.execute();
		} catch(Exception e) {
			MTalkLogWriter.e(e);
		}
	}
	
	public void downloadFile(Message message) {
		try{
			Toast.makeText(mContext, "파일 다운로드를 시작하자", Toast.LENGTH_SHORT).show();
			
			ImageOption imageOption = new ImageOption();
			imageOption.setWidth(ChatListCursorAdapter.THUMB_MAX_SIZE_DIP);
			imageOption.setHeight(ChatListCursorAdapter.THUMB_MAX_SIZE_DIP);
			
			FileDownloadTask task = new FileDownloadTask(mContext, mUiHandler,
					InboxDatabaseHelper.getClientUUID(mContext, message.getViewUuid()),
					null, message.getUserMassage().getAttachFile(), imageOption);
			task.execute();
		} catch (Exception e) {
			MTalkLogWriter.e(e);
		}
	}
	
	public void downloadThumbnail(Message message) {
		try{
			ImageOption imageOption = new ImageOption();
			imageOption.setHeight(40);
			imageOption.setWidth(40);
			Toast.makeText(mContext, "ThumbnailDownload", Toast.LENGTH_SHORT).show();
			FileDownloadTask task = new FileDownloadTask(mContext, mUiHandler, InboxDatabaseHelper.getClientUUID(mContext, message.getViewUuid()),
					null, message.getUserMassage().getAttachFile(), imageOption);
			task.execute();
		} catch (Exception e) {
			MTalkLogWriter.e(e);
		}
	}

	// TODO 삭제
	/*public void onNetResult(int resultCode, Object request, Object result) {
		TcpEnvelope rev = (TcpEnvelope) result;
		switch (rev.getMethodId()) {
			case MethodId.Messaging.SendMessage :
				resultSendMessage(rev.getRequestId(), (Session.SendMessageRes) rev.getMessage());
				break;
			case MethodId.Messaging.Subscrbe :
				resultSubscribe(rev.getRequestId(), (Session.SubscrbeRes) rev.getMessage());
				break;
			case MethodId.Messaging.Unsubscribe :
				resultUnsubscribe(rev.getRequestId(), (Session.UnsubscribeRes) rev.getMessage());
				break;
			case MethodId.Messaging.GetMessages:
				resultGetMessages(resultCode, (GetMessagesRes)rev.getMessage());
				break;
			case MethodId.DelieverMessages.DeliverMessages :
				Log.d(HanlderMsgConst.TAG, "onNetResult() : deliver message ");
				break;
			case MethodId.File.AcquireFileToken :
				resultFileTocken(rev.getRequestId(), (AcquireFileTokenRes)rev.getMessage());
				break;
			case MethodId.File.UploadFile :
				resultUploadFile();
				break;
		}
	}*/
	

	private void resultFileTocken(int requestId, AcquireFileTokenRes tockenRes) {
		if( tockenRes.getResponseCode()==200 ){
			// ATTACHMENT 2. UPLOAD FILE BY USING FILE-TOKEN
		} else {
			
		}
	}
	
	private void resultUploadFile(){
		// ATTACHMENT 3. SEND MESSAGE
		SendMessageReq sendMessageReq = new SendMessageReq();
		UserMessage userMessage = new UserMessage();
		userMessage.setContentType(1); // ContentType enum
		userMessage.setContent("");	// TODO 각각 첨부파일 타입에 맞춰 설정한다
		userMessage.setSenderUuid(GpbSupport.makeUuidMsg(333, 444));
		userMessage.setSessionUuid(GpbSupport.makeUuidMsg(7777, 8888));
		//userMessage..setAttachment(0, new FileKey());	// TODO 결과로 온 파일키를 넣어준다
		sendMessageReq.setMessage(userMessage);
		
		//sendMessage(context, sendMessageReq, MessageProperty.IMAGE, null); // TODO 각각 첨부파일 타입에 맞춰 설정
	}
	
	/**
	 * 데이터 베이스에서 메시지를 읽어와서 메일 내용에 적고 sendmail 인텐트를 호출한다.
	 * (PreExecute 에서 null 을 리턴해서 네트워크 작업을 하지 않는다.)
	 * @param clientViewUuid
	 */
	public void backupHistoryMessage(UUID clientViewUuid){
		try{
			MTalkLogWriter.d("InboxController.backupHistoryMessage()");
			DBBackupHistoryMessagesTask task = new DBBackupHistoryMessagesTask(mContext, mUiHandler, clientViewUuid);
			task.execute();
		} catch(Exception e) {
			MTalkLogWriter.e(e);
		}
	}
	
	/**
	 * 모든 메시지를 받아온다.
	 * @param clientViewUuidMsb
	 * @param clientViewUuidLsb
	 */
	public void getMessages(long clientViewUuidMsb, long clientViewUuidLsb) {
		UUIDMsg viewUuid = InboxDatabaseHelper.getViewUUID(mContext, clientViewUuidMsb, clientViewUuidLsb);
		GetMessagesReq getMessagesReq = new GetMessagesReq();
		getMessagesReq.setViewUuid(viewUuid);
		UUIDSliceRange range = new UUIDSliceRange();
		range.setAscending(false);
		range.setMaxCount(ChatListActivity.GET_MESSAGE_MAX_COUNT);
		getMessagesReq.setRange(range);
		
		GetMessagesTask task = new GetMessagesTask(mContext, mUiHandler, viewUuid, getMessagesReq);
		task.execute();
	}

	public void addMember(AddMembersReq addMembersReq) {
		AddMembersTask task = new AddMembersTask(mContext, mUiHandler, addMembersReq);
		task.execute();
	}
}
